package util

import (
	"io/ioutil"
	"os"
	"strings"

	"golang.org/x/mod/modfile"
)

func ParseGoModFile(modFile string) (*modfile.File, error) {
	modF, err := os.Open(modFile)
	if err != nil {
		return nil, err
	}
	defer modF.Close()
	modContents, err := ioutil.ReadAll(modF)
	if err != nil {
		return nil, err
	}
	mod, err := modfile.Parse(modFile, modContents, nil)
	if err != nil {
		return nil, err
	}
	return mod, nil
}

func MergeSubMod(mainMod, subMod *modfile.File) error {
	for i := 0; i < len(subMod.Require); i++ {
		mainMod.AddRequire(subMod.Require[i].Mod.Path, subMod.Require[i].Mod.Version)
	}
	for i := 0; i < len(subMod.Replace); i++ {
		mainMod.AddReplace(subMod.Replace[i].Old.Path, subMod.Replace[i].Old.Version,
			subMod.Replace[i].New.Path, subMod.Replace[i].New.Version)
	}
	for i := 0; i < len(subMod.Exclude); i++ {
		mainMod.AddExclude(subMod.Exclude[i].Mod.Path, subMod.Exclude[i].Mod.Version)
	}
	return nil
}

func GenerateNewModFile(modF *modfile.File, outPutFile string) error {
	bs, bsErr := modF.Format()
	if bsErr != nil {
		return bsErr
	}
	return os.WriteFile(outPutFile, bs, 0666)
}

const (
	ContractSdkPackage = "chainmaker.org/chainmaker/contract-sdk-go/v2"
)

var (
	filteredVersions = []string{"v2.3.0", "v2.3.1", "v2.3.2", "v2.3.3", "v2.3.4"}
)

func CheckContractSdkNotAddTag(modFile string) (bool, error) {
	// 0. has no contract sdk package , return true
	// 1. has contract sdk package && in filteredVersions return true
	// retrun false
	parsed, parsedErr := ParseGoModFile(modFile)
	if parsedErr != nil {
		return true, parsedErr
	}
	hasContractSdk := false
	var version string
	for _, tmpR := range parsed.Require {
		if strings.Contains(tmpR.Mod.Path, ContractSdkPackage) {
			version = tmpR.Mod.Version
			hasContractSdk = true
			break
		}
	}
	if !hasContractSdk {
		return true, nil
	}
	for _, tmpF := range filteredVersions {
		if strings.Contains(version, tmpF) {
			return true, nil
		}
	}
	return false, nil
}
